﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SingletonPattern
{
    /// <summary>
    /// 单例模式
    /// </summary>
    public class Singleton
    {
        #region  1.这种单例线程不安全

        ///// <summary>
        ///// 私有构造器
        ///// </summary>
        //private Singleton() { }

        ////静态对象 用作单例判断
        //private static Singleton _Singleton = null;

        ///// <summary>
        ///// 创建单例方法
        ///// </summary>
        ///// <returns>单例对象</returns>
        //public static Singleton CreateInstance()
        //{
        //    //当单例对象为空时,创建Static对象,这种写法线程不安全。
        //    if (_Singleton == null)
        //    {
        //        Console.WriteLine("被创建");
        //        _Singleton = new Singleton();
        //    }
        //    return _Singleton;
        //}
        #endregion

        #region 2.对不安全得线程做改进(加锁),第一次进入时创建对象,后续不创建新对象
        ////私有构造器
        //private Singleton() { }

        ////单例对象
        //private static Singleton _Singleton = null;

        ////同步锁对象
        //private static object Singleton_Lock = new object();

        ///// <summary>
        ///// 创建单例
        ///// </summary>
        ///// <returns>单例对象</returns>
        //public static Singleton CreateInstance()
        //{
        //    //对锁对象加锁
        //    lock (Singleton_Lock)
        //    {
        //        //判断单利对象为空时,创建对象
        //        if (_Singleton == null)
        //        {
        //            Console.WriteLine("被创建");
        //            _Singleton = new Singleton();
        //        }
        //        else
        //        {
        //            //不为空时,说明对象已经被创建
        //            Console.WriteLine("已经被创建");
        //        }
        //    }
        //    //返回单例对象
        //    return _Singleton;
        //}

        #endregion

        #region 3.对2进行优化,2中得锁本身也消耗资源,我们在外侧再判断一次单例对象是否存在
        //单例对象
        private static Singleton _Singleton = null;
        //锁对象
        private static object Singleton_Lock = new object();
        //获取单例对象
        public static Singleton CreateInstance()
        {
            //如果单例对象为空,再去锁
            if (_Singleton == null) //双if +lock
            {
                //锁对象
                lock (Singleton_Lock)
                {
                    Console.WriteLine($"已经被创建,返回单例对象，这里有100个线程,但是由于做了双重单例对象Null判断,大量任务会被挡在锁外面,提升效率");
                    //如果单例对象为空,创建单例对象
                    if (_Singleton == null)
                    {
                        Console.WriteLine("被创建。");
                        _Singleton = new Singleton();
                    }
                }
            }
            return _Singleton;
        }
        #endregion
    }
}
